#ifndef _utility_logger_h
#define _utility_logger_h

#include <string>
#include <fstream>


#define MEM_1K (1024*1)
#define MEM_4K (1024*4)
#define MEM_1M (1024*1024)

using namespace std;

namespace ddserver 
{
namespace utility
{

#define log_debug(format, ...) \
    Logger::instance()->log(Logger::Level::DEBUG, __FILE__, __LINE__, format, ##__VA_ARGS__)

#define log_info(format, ...) \
    Logger::instance()->log(Logger::Level::INFO, __FILE__, __LINE__, format, ##__VA_ARGS__)

#define log_warn(format, ...) \
    Logger::instance()->log(Logger::Level::WARN, __FILE__, __LINE__, format, ##__VA_ARGS__)

#define log_error(format, ...) \
    Logger::instance()->log(Logger::Level::ERR, __FILE__, __LINE__, format, ##__VA_ARGS__)

#define fatal(format, ...) \
    Logger::instance()->log(Logger::Level::FATAL, __FILE__, __LINE__, format, ##__VA_ARGS__)


class Logger
{
public:
    enum Level
    {
        DEBUG = 0,
        INFO,
        WARN,
        ERR,
        FATAL,
        LEVEL_COUNT
    };

    static Logger* instance();
    void open(const string &filename);
    void close();
    void log(Level level, const char* file, int line, const char* format, ...);
    void max(int bytes);
    void level(int level);

private:
    Logger();
    ~Logger();
    void rotate();

private:
    string m_filename;
    ofstream m_fout;
    int m_max;
    int m_len;
    int m_level;
    static const char* s_level[LEVEL_COUNT];
    static Logger *m_instance;
};

}
}

#endif